/**
 * MovingObstacle - 移动障碍物
 * 具有动态移动行为的障碍物，增加游戏难度和挑战性
 */

import { Obstacle, ObstacleType, ObstacleOptions, ObstacleBehavior } from '../Obstacle'
import type { Entity } from '../Entity'
import type { Vector2D } from '../GameEngine'

/**
 * 移动模式枚举
 */
export enum MovementPattern {
  HORIZONTAL = 'horizontal',    // 水平移动
  VERTICAL = 'vertical',       // 垂直移动
  CIRCULAR = 'circular',       // 圆形移动
  PENDULUM = 'pendulum',       // 钟摆移动
  ZIGZAG = 'zigzag'           // 之字形移动
}

/**
 * 移动障碍物配置选项
 */
export interface MovingObstacleOptions extends Omit<ObstacleOptions, 'obstacleType'> {
  movementPattern?: MovementPattern
  speed?: number
  amplitude?: number
  frequency?: number
  initialDirection?: Vector2D
}

/**
 * 移动行为实现
 */
class MovementBehavior implements ObstacleBehavior {
  private pattern: MovementPattern
  private speed: number
  private amplitude: number
  private frequency: number
  private time: number = 0
  private initialPosition: Vector2D
  // private direction: Vector2D

  /**
   * 创建移动行为
   * @param pattern - 移动模式
   * @param speed - 移动速度
   * @param amplitude - 移动幅度
   * @param frequency - 移动频率
   * @param initialDirection - 初始方向
   */
  constructor(
    pattern: MovementPattern,
    speed: number,
    amplitude: number,
    frequency: number,
    _initialDirection: Vector2D
  ) {
    this.pattern = pattern
    this.speed = speed
    this.amplitude = amplitude
    this.frequency = frequency
    // this.direction = { ...initialDirection }
    this.initialPosition = { x: 0, y: 0 }
  }

  /**
   * 更新移动行为
   * @param obstacle - 障碍物实例
   * @param deltaTime - 时间差
   */
  update(obstacle: Obstacle, deltaTime: number): void {
    const movingObstacle = obstacle as unknown as MovingObstacle
    if (this.time === 0) {
      // 记录初始位置
      this.initialPosition = { x: obstacle.x, y: obstacle.y }
    }

    this.time += deltaTime

    switch (this.pattern) {
      case MovementPattern.HORIZONTAL:
        this.updateHorizontalMovement(movingObstacle)
        break
      case MovementPattern.VERTICAL:
        this.updateVerticalMovement(movingObstacle)
        break
      case MovementPattern.CIRCULAR:
        this.updateCircularMovement(movingObstacle)
        break
      case MovementPattern.PENDULUM:
        this.updatePendulumMovement(movingObstacle)
        break
      case MovementPattern.ZIGZAG:
        this.updateZigzagMovement(movingObstacle)
        break
    }
  }

  /**
   * 更新水平移动
   * @param obstacle - 障碍物实例
   */
  private updateHorizontalMovement(obstacle: MovingObstacle): void {
    const offset = Math.sin(this.time * this.frequency * 0.001) * this.amplitude
    obstacle.y = this.initialPosition.y + offset
    obstacle.setVelocity(-this.speed, 0) // 向左移动
  }

  /**
   * 更新垂直移动
   * @param obstacle - 障碍物实例
   */
  private updateVerticalMovement(obstacle: MovingObstacle): void {
    const offset = Math.sin(this.time * this.frequency * 0.001) * this.amplitude
    obstacle.x = this.initialPosition.x + offset
    obstacle.setVelocity(-this.speed, 0) // 向左移动
  }

  /**
   * 更新圆形移动
   * @param obstacle - 障碍物实例
   */
  private updateCircularMovement(obstacle: MovingObstacle): void {
    const angle = this.time * this.frequency * 0.001
    const offsetX = Math.cos(angle) * this.amplitude
    const offsetY = Math.sin(angle) * this.amplitude
    
    obstacle.x = this.initialPosition.x + offsetX - this.speed * (this.time * 0.001)
    obstacle.y = this.initialPosition.y + offsetY
  }

  /**
   * 更新钟摆移动
   * @param obstacle - 障碍物实例
   */
  private updatePendulumMovement(obstacle: MovingObstacle): void {
    const angle = Math.sin(this.time * this.frequency * 0.001) * (Math.PI / 4) // 45度摆动
    const offsetX = Math.sin(angle) * this.amplitude
    const offsetY = Math.cos(angle) * this.amplitude - this.amplitude
    
    obstacle.x = this.initialPosition.x + offsetX - this.speed * (this.time * 0.001)
    obstacle.y = this.initialPosition.y + offsetY
  }

  /**
   * 更新之字形移动
   * @param obstacle - 障碍物实例
   */
  private updateZigzagMovement(obstacle: MovingObstacle): void {
    const zigzagPhase = Math.floor(this.time * this.frequency * 0.001) % 2
    const progress = (this.time * this.frequency * 0.001) % 1
    
    let offsetY = 0
    if (zigzagPhase === 0) {
      offsetY = progress * this.amplitude
    } else {
      offsetY = this.amplitude - (progress * this.amplitude)
    }
    
    obstacle.x = this.initialPosition.x - this.speed * (this.time * 0.001)
    obstacle.y = this.initialPosition.y + offsetY - this.amplitude / 2
  }

  /**
   * 重置行为状态
   */
  reset(): void {
    this.time = 0
    this.initialPosition = { x: 0, y: 0 }
  }
}

/**
 * 移动障碍物类
 * @class
 * @example
 * const movingObstacle = new MovingObstacle({
 *   x: 500,
 *   y: 200,
 *   width: 40,
 *   height: 40,
 *   movementPattern: MovementPattern.CIRCULAR,
 *   speed: 100,
 *   amplitude: 50
 * });
 */
export class MovingObstacle extends Obstacle {
  public readonly movementPattern: MovementPattern
  public readonly baseSpeed: number
  public readonly amplitude: number
  public readonly frequency: number
  private animationTime: number = 0
  private trailPositions: Array<{x: number, y: number, alpha: number}> = []

  /**
   * 创建移动障碍物
   * @param options - 移动障碍物配置选项
   */
  constructor(options: MovingObstacleOptions) {
    const pattern = options.movementPattern || MovementPattern.HORIZONTAL
    const speed = options.speed || 50
    const amplitude = options.amplitude || 30
    const frequency = options.frequency || 1
    const initialDirection = options.initialDirection || { x: -1, y: 0 }

    // 创建移动行为
    const movementBehavior = new MovementBehavior(
      pattern,
      speed,
      amplitude,
      frequency,
      initialDirection
    )

    super({
      ...options,
      obstacleType: ObstacleType.MOVING,
      behavior: movementBehavior,
      damage: MovingObstacle.getDamageByPattern(pattern),
      scoreValue: MovingObstacle.getScoreByPattern(pattern),
      canBeDestroyed: false // 移动障碍物通常不能被摧毁
    })

    this.movementPattern = pattern
    this.baseSpeed = speed
    this.amplitude = amplitude
    this.frequency = frequency
  }

  /**
   * 根据移动模式获取伤害值
   * @param pattern - 移动模式
   * @returns 伤害值
   */
  private static getDamageByPattern(pattern: MovementPattern): number {
    switch (pattern) {
      case MovementPattern.HORIZONTAL:
        return 2
      case MovementPattern.VERTICAL:
        return 2
      case MovementPattern.CIRCULAR:
        return 3
      case MovementPattern.PENDULUM:
        return 3
      case MovementPattern.ZIGZAG:
        return 4
      default:
        return 2
    }
  }

  /**
   * 根据移动模式获取分数值
   * @param pattern - 移动模式
   * @returns 分数值
   */
  private static getScoreByPattern(pattern: MovementPattern): number {
    switch (pattern) {
      case MovementPattern.HORIZONTAL:
        return 40
      case MovementPattern.VERTICAL:
        return 45
      case MovementPattern.CIRCULAR:
        return 60
      case MovementPattern.PENDULUM:
        return 55
      case MovementPattern.ZIGZAG:
        return 70
      default:
        return 40
    }
  }

  /**
   * 更新移动障碍物逻辑
   * @param deltaTime - 时间差
   */
  protected updateObstacle(deltaTime: number): void {
    this.animationTime += deltaTime

    // 更新轨迹记录
    this.updateTrail()

    // 添加旋转效果（视觉）
    this.updateRotationEffect(deltaTime)
  }

  /**
   * 更新轨迹记录
   */
  private updateTrail(): void {
    // 添加当前位置到轨迹
    this.trailPositions.unshift({
      x: this.x + this.width / 2,
      y: this.y + this.height / 2,
      alpha: 1.0
    })

    // 更新轨迹透明度并移除过旧的点
    this.trailPositions = this.trailPositions
      .map(pos => ({ ...pos, alpha: pos.alpha - 0.05 }))
      .filter(pos => pos.alpha > 0)
      .slice(0, 20) // 最多保留20个轨迹点
  }

  /**
   * 更新旋转效果
   * @param _deltaTime - 时间差
   */
  private updateRotationEffect(_deltaTime: number): void {
    // 这里可以添加旋转逻辑，用于渲染时的视觉效果
    // 实际的旋转角度可以存储在私有属性中
  }

  /**
   * 渲染移动障碍物
   * @param ctx - Canvas渲染上下文
   */
  render(ctx: CanvasRenderingContext2D): void {
    if (!this.visible) return

    // 渲染轨迹
    this.renderTrail(ctx)

    // 渲染主体
    if (this.sprite && this.sprite.image) {
      super.render(ctx)
    } else {
      this.renderDefault(ctx)
    }

    // 渲染移动指示器
    this.renderMovementIndicator(ctx)
  }

  /**
   * 渲染轨迹
   * @param ctx - Canvas渲染上下文
   */
  private renderTrail(ctx: CanvasRenderingContext2D): void {
    for (let i = 0; i < this.trailPositions.length - 1; i++) {
      const current = this.trailPositions[i]
      const next = this.trailPositions[i + 1]
      
      ctx.strokeStyle = `rgba(255, 100, 100, ${current.alpha * 0.5})`
      ctx.lineWidth = 3 * current.alpha
      ctx.beginPath()
      ctx.moveTo(current.x, current.y)
      ctx.lineTo(next.x, next.y)
      ctx.stroke()
    }
  }

  /**
   * 渲染默认外观
   * @param ctx - Canvas渲染上下文
   */
  protected renderDefault(ctx: CanvasRenderingContext2D): void {
    // 主体颜色
    const gradient = ctx.createRadialGradient(
      this.x + this.width / 2,
      this.y + this.height / 2,
      0,
      this.x + this.width / 2,
      this.y + this.height / 2,
      Math.max(this.width, this.height) / 2
    )
    gradient.addColorStop(0, '#FF6B6B')
    gradient.addColorStop(0.7, '#FF4444')
    gradient.addColorStop(1, '#CC0000')

    ctx.fillStyle = gradient
    ctx.fillRect(this.x, this.y, this.width, this.height)

    // 添加发光效果
    const glowIntensity = (Math.sin(this.animationTime * 0.01) + 1) / 2
    ctx.shadowColor = '#FF4444'
    ctx.shadowBlur = 10 * glowIntensity
    ctx.fillRect(this.x, this.y, this.width, this.height)
    ctx.shadowBlur = 0

    // 添加移动模式特有的视觉标识
    this.renderPatternIndicator(ctx)
  }

  /**
   * 渲染移动模式指示器
   * @param ctx - Canvas渲染上下文
   */
  private renderPatternIndicator(ctx: CanvasRenderingContext2D): void {
    const centerX = this.x + this.width / 2
    const centerY = this.y + this.height / 2
    
    ctx.strokeStyle = '#FFFFFF'
    ctx.lineWidth = 2
    
    switch (this.movementPattern) {
      case MovementPattern.HORIZONTAL:
        // 水平箭头
        ctx.beginPath()
        ctx.moveTo(centerX - 8, centerY)
        ctx.lineTo(centerX + 8, centerY)
        ctx.moveTo(centerX + 4, centerY - 4)
        ctx.lineTo(centerX + 8, centerY)
        ctx.lineTo(centerX + 4, centerY + 4)
        ctx.stroke()
        break
        
      case MovementPattern.VERTICAL:
        // 垂直箭头
        ctx.beginPath()
        ctx.moveTo(centerX, centerY - 8)
        ctx.lineTo(centerX, centerY + 8)
        ctx.moveTo(centerX - 4, centerY + 4)
        ctx.lineTo(centerX, centerY + 8)
        ctx.lineTo(centerX + 4, centerY + 4)
        ctx.stroke()
        break
        
      case MovementPattern.CIRCULAR:
        // 圆形指示器
        ctx.beginPath()
        ctx.arc(centerX, centerY, 6, 0, Math.PI * 2)
        ctx.stroke()
        break
        
      case MovementPattern.PENDULUM:
        // 钟摆指示器
        ctx.beginPath()
        ctx.arc(centerX, centerY - 6, 3, 0, Math.PI * 2)
        ctx.moveTo(centerX, centerY - 6)
        ctx.lineTo(centerX, centerY + 6)
        ctx.stroke()
        break
        
      case MovementPattern.ZIGZAG:
        // 之字形指示器
        ctx.beginPath()
        ctx.moveTo(centerX - 8, centerY - 4)
        ctx.lineTo(centerX - 2, centerY + 4)
        ctx.lineTo(centerX + 4, centerY - 4)
        ctx.lineTo(centerX + 8, centerY + 4)
        ctx.stroke()
        break
    }
  }

  /**
   * 渲染移动指示器
   * @param ctx - Canvas渲染上下文
   */
  private renderMovementIndicator(ctx: CanvasRenderingContext2D): void {
    // 在障碍物周围绘制移动方向指示器
    const alpha = (Math.sin(this.animationTime * 0.008) + 1) / 2 * 0.5 + 0.3
    ctx.strokeStyle = `rgba(255, 255, 0, ${alpha})`
    ctx.lineWidth = 2
    ctx.setLineDash([5, 5])
    ctx.strokeRect(this.x - 5, this.y - 5, this.width + 10, this.height + 10)
    ctx.setLineDash([]) // 重置虚线
  }

  /**
   * 处理碰撞逻辑
   * @param player - 玩家实体
   * @returns 是否处理了碰撞
   */
  protected handleCollision(_player: Entity): boolean {
    console.log(`玩家与${this.movementPattern}移动障碍物碰撞，造成${this.damage}点伤害`)
    
    // 移动障碍物碰撞后可能会改变移动模式或速度
    this.onCollisionEffect()
    
    return true
  }

  /**
   * 碰撞后的特殊效果
   */
  private onCollisionEffect(): void {
    // 可以添加碰撞后的特殊行为，比如：
    // - 改变移动速度
    // - 改变移动方向
    // - 触发特殊动画
  }

  /**
   * 获取预测位置（用于AI或高级碰撞检测）
   * @param timeAhead - 预测的时间（毫秒）
   * @returns 预测位置
   */
  getPredictedPosition(timeAhead: number): Vector2D {
    // 这里可以根据当前的移动模式和速度预测未来位置
    // 简化实现：假设匀速直线运动
    return {
      x: this.x + this.velocity.x * (timeAhead / 1000),
      y: this.y + this.velocity.y * (timeAhead / 1000)
    }
  }

  /**
   * 获取移动范围
   * @returns 移动范围边界
   */
  getMovementBounds(): { minX: number, maxX: number, minY: number, maxY: number } {
    return {
      minX: this.x - this.amplitude,
      maxX: this.x + this.amplitude,
      minY: this.y - this.amplitude,
      maxY: this.y + this.amplitude
    }
  }

  /**
   * 获取障碍物描述
   * @returns 描述信息
   */
  getDescription(): string {
    const baseDesc = super.getDescription()
    return `${baseDesc} - ${this.movementPattern}移动模式 (速度: ${this.baseSpeed}, 幅度: ${this.amplitude})`
  }
}